package com.sun.androidexerciseproject.function.activity;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.TextView;

import com.sun.androidexerciseproject.function.R;
import com.sun.androidexerciseproject.function.model.Person;
import com.sun.androidexerciseproject.function.security.DHCoder;
import com.sun.androidexerciseproject.function.security.RSA;
import com.sun.androidexerciseproject.function.security.RSAUtil;
import com.sun.androidexerciseproject.function.test.TestClass;
import com.sun.androidexerciseproject.function.util.CipherTest;
import com.sun.androidexerciseproject.function.util.LogUtil;
import com.sun.androidexerciseproject.function.util.NetworkUtil;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import pub.devrel.easypermissions.EasyPermissions;

import static android.util.Base64.DEFAULT;

public class MainActivity extends AppCompatActivity implements View.OnClickListener, EasyPermissions.PermissionCallbacks {
    public static final int DEVICE_PERMISSION = 1;
    String webUrl1 = "https://www.bjtime.cn";//bjTime
    String webUrl2 = "http://www.baidu.com";//百度
    String webUrl3 = "https://www.taobao.com";//淘宝
    String webUrl4 = "http://www.ntsc.ac.cn";//中国科学院国家授时中心
    String webUrl5 = "http://www.360.cn";//360
    String webUrl6 = "http://www.beijing-time.org";//beijing-time
    BlockingQueue queue = new LinkedBlockingQueue();
    ThreadPoolExecutor mThreadPoolExecutor = new ThreadPoolExecutor(3, 6, 1, TimeUnit.DAYS, queue);
    private Button mBtnTime1;
    private Button mBtnTime2;
    private Button mBtnTime3;
    private TextView mTvTime1;
    private TextView mTvTime2;
    private TextView mTvTime3;
    private TextView tvIp;
    private Button mBtnStartService;
    private HandlerThread mHandlerThread;
    /**
     * handlder是一个一个执行，连着发送两个消息也是一个个执行
     */
    private Handler mWorkHandler;
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            int id = msg.what;
            long time = (long) msg.obj;
            if (id == R.id.btn_time1) {
                mTvTime1.setText(String.valueOf(time));
            } else if (id == R.id.btn_time2) {
                mTvTime2.setText(String.valueOf(time));
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        startBrowser();
        test();
        setContentView(R.layout.activity_main);
        initView();
        getSystemInfo();
        cipherTest();
        byteArrayTest();
        String plainText = "Hi,RSA";
        RSA rsa = RSA.getInstance();
        String privateKey = rsa.getPrivateKey();
        String encryptText = rsa.encrypyByPublic(plainText);
        LogUtil.log("plainText = " + plainText);
        LogUtil.log("encryptText = " + encryptText);
        LogUtil.log("privateKey = " + privateKey);
        Random random = new Random();
        int value = random.nextInt(1000);
        LogUtil.log("value1 = " + value);
        value = random.nextInt();
        LogUtil.log("value2 = " + value);
        testReflectMethod();
        mHandlerThread = new HandlerThread("workThread");
        mHandlerThread.start();
        mWorkHandler = new Handler(mHandlerThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                int what = msg.what;
                switch (what) {
                    case 1:
                        long time = System.currentTimeMillis();
                        System.out.println("time111 begin1" + time);
                        for (int i = 0; i < Integer.MAX_VALUE; i++) {

                        }
                        time = System.currentTimeMillis();
                        System.out.println("time111 end1 " + time);
                        break;
                    case 2:
                        System.out.println("time111 begin2 " + System.currentTimeMillis());
                        break;
                }
            }
        };
        try {
            rsaTest();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void byteArrayTest() {
        byte[] testArray = {'2', '3', '4', '5', '6'};
        String testStr = new String(testArray);
        byte[] afterArray = testStr.getBytes();
        if (Arrays.equals(testArray, afterArray)) {
            System.out.println("byteArrayTest == ");
        } else {
            System.out.println("byteArrayTest != ");
        }

    }

    private void initView() {
        mBtnTime1 = findViewById(R.id.btn_time1);
        mBtnTime2 = findViewById(R.id.btn_time2);
        mBtnTime3 = findViewById(R.id.btn_time3);
        mTvTime1 = findViewById(R.id.tv_time1);
        mTvTime2 = findViewById(R.id.tv_time2);
        mTvTime3 = findViewById(R.id.tv_time3);
        tvIp = findViewById(R.id.tv_ip);

        mBtnTime1.setOnClickListener(this);
        mBtnTime2.setOnClickListener(this);
        mBtnTime3.setOnClickListener(this);
        tvIp.setOnClickListener(this);
        mBtnStartService = findViewById(R.id.btn_start_service);
        mBtnStartService.setOnClickListener(v -> {
            mWorkHandler.sendEmptyMessage(1);
            mWorkHandler.sendEmptyMessage(2);
        });

    }

    protected void getDeviceID() {
        if (EasyPermissions.hasPermissions(this, Manifest.permission.READ_PHONE_STATE)) {
            doGetDeviceId();
        } else {
            EasyPermissions.requestPermissions(this, "getDeviceID", DEVICE_PERMISSION, Manifest.permission.READ_PHONE_STATE);
        }
    }

    private void doGetDeviceId() {
        TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        @SuppressLint("MissingPermission") String deviceID = telephonyManager.getDeviceId();
        LogUtil.log("deveceId = " + deviceID);
    }

    private void cipherTest() {
        CipherTest.base64Test();
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        switch (id) {
            case R.id.btn_time1: {
                getTime(webUrl2, id);
                break;
            }
            case R.id.btn_time2: {
                getTime(webUrl3, id);
                break;
            }
            case R.id.btn_time3:
//                if (!TextUtils.isEmpty(mTvTime1.getText().toString()) && !TextUtils.isEmpty(mTvTime2.getText().toString())) {
//                    long time = Long.parseLong(mTvTime2.getText().toString()) - Long.parseLong(mTvTime1.getText().toString());
//                    mTvTime3.setText(String.valueOf(time));
//                    mTvTime1.setText("");
//                    mTvTime2.setText("");
//                }
                testDH();
                break;
            case R.id.tv_ip:
                getIp();
                getDeviceID();
                break;
            default:
                break;

        }
    }

    private void testDH() {
        mThreadPoolExecutor.execute(new Runnable() {
            @Override
            public void run() {
            }
        });
    }

    private void getIp() {
        LogUtil.log("getIp ");
        mThreadPoolExecutor.execute(new Runnable() {
            @Override
            public void run() {
                LogUtil.log("testIp ");
                NetworkUtil.testIp();
            }
        });
    }

    private void getTime(String webUrl, int id) {
        mThreadPoolExecutor.execute(new Runnable() {
            @Override
            public void run() {
                long beginTime = System.currentTimeMillis();

                long ld = -1;
                try {
                    URL url = new URL(webUrl);// 取得资源对象
                    URLConnection uc = url.openConnection();// 生成连接对象
                    uc.connect();// 发出连接
                    ld = uc.getDate();// 读取网站日期时间
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }

                long usedTime = System.currentTimeMillis() - beginTime;
                long threadId = Thread.currentThread().getId();
                LogUtil.log(String.format("Time = %d, threadId = %d", usedTime, threadId));
                Message message = Message.obtain();
                message.what = id;
                message.obj = ld;
                mHandler.sendMessage(message);
            }
        });
    }

    private void getSystemInfo() {
        LogUtil.log(String.format("Model = %s, SDK = %d, RELEASE = %s, FAC = %s", Build.MODEL, Build.VERSION.SDK_INT
                , Build.VERSION.RELEASE, Build.MANUFACTURER));
    }

    @Override
    public void onPermissionsGranted(int requestCode, List<String> perms) {
        LogUtil.log("onPermissionsGranted requestCode = " + requestCode);
    }

    @Override
    public void onPermissionsDenied(int requestCode, List<String> perms) {
        LogUtil.log("onPermissionsDenied requestCode = " + requestCode);
    }

    private void testReflectMethod() {
        try {
            Class<?> cls = Class.forName("com.sun.androidexerciseproject.function.test.TestClass");
            Method method = cls.getDeclaredMethod("Test");
            method.setAccessible(true);
            TestClass testClass = (TestClass) cls.newInstance();
            method.invoke(testClass);
        } catch (ClassNotFoundException e) {
            LogUtil.log("ClassNotFoundException exception message " + e.getMessage());
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            LogUtil.log("NoSuchMethodException exception message " + e.getMessage());
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            LogUtil.log("IllegalAccessException exception message " + e.getMessage());
            e.printStackTrace();
        } catch (InstantiationException e) {
            LogUtil.log("InstantiationException exception message " + e.getMessage());
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            LogUtil.log("InvocationTargetException exception message " + e.getMessage());
            e.printStackTrace();
        }
    }

    private void startBrowser() {
        String url = "HTTPS://QR.ALIPAY.COM/FKX03142QV4J4469QKQ0FC";
        WebView webView = new WebView(this);
        WebSettings settings = webView.getSettings();
        settings.setJavaScriptEnabled(true);
        settings.setAllowFileAccess(false);
        settings.setSupportZoom(false);
        settings.setBlockNetworkImage(true);
        settings.setAppCacheEnabled(true);
        settings.setJavaScriptCanOpenWindowsAutomatically(true);
        settings.setCacheMode(WebSettings.LOAD_DEFAULT);
        if (Build.VERSION.SDK_INT >= 19) {
            settings.setLoadsImagesAutomatically(true);
            settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING);
        } else {
            settings.setLoadsImagesAutomatically(false);
            settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
        }
        settings.setDomStorageEnabled(true);
        settings.setBlockNetworkLoads(false);
        webView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                boolean ret = isPayUrl(url);
                System.out.println("url = " + url);
                if (ret) {
                    wapPay(url);
                    return true;
                }
                if (url.contains("scheme=")) {
                    int index = url.indexOf("scheme=");
                    index += "scheme=".length();
                    String shortUrl = url.substring(index);
                    shortUrl = URLDecoder.decode(shortUrl);
                    if (isPayUrl(shortUrl)) {
                        wapPay(url);
                        return true;
                    }
                }
                return false;
            }
        });
        webView.loadUrl(url);
    }

    private boolean isPayUrl(String url) {
        return url.startsWith("alipays://") || url.contains("alipayqr");
    }

    private void wapPay(String url) {
        Intent intent;
        try {
            intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
            intent.addCategory(Intent.CATEGORY_BROWSABLE);
            intent.setComponent(null);
            intent.setSelector(null);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
        } catch (URISyntaxException | ActivityNotFoundException e) {
            e.printStackTrace();
        }
    }

    private void test() {
        String testStr = "1|2|3";
        String[] arr = testStr.split("\\|");
        for (String str : arr) {
            System.out.println("test arr " + str);
        }
        Test test = new Test("11", "22");
        testReflect();
        com.sun.androidexerciseproject.function.security.CipherTest cipherTest = new com.sun.androidexerciseproject.function.security.CipherTest();
        cipherTest.encode("TestMessage");
        try {
            testCipher();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void testReflect() {
        try {
            throw new RuntimeException("testReflect RuntimeException");

        } catch (Exception e) {
            System.out.println("testReflect " + e.getMessage());

            System.out.println("testReflect content " + Log.getStackTraceString(e));
        }
        Object[] args = new String[]{"beijing", "11"};
        try {
//            Object person = newInstance("com.sun.androidexerciseproject.function.activity.MainActivity$Test", args);
            Test person = new Test("lilei", "Beijing");
            String name = (String) getProperty(person, "name");
            String age = (String) getProperty(person, "age");
            System.out.println(String.format("age = %s, name = %s", age, name));
        } catch (Exception e) {
            e.printStackTrace();
        }
        String[] testArr = new String[16];
        Arrays.fill(testArr, "123");
        for (String test : testArr) {
            System.out.println("array test " + test);
        }
        Person[] persons = new Person[15];
        Arrays.fill(persons, new Person(33, "zhangsan", "Beijing"));
        for (Person test : persons) {
            System.out.println("Person array test " + test);
        }
    }


    private Object getProperty(Object owner, String filedName) {
        Class<?> ownerCls = owner.getClass();
        try {
            Field field = ownerCls.getDeclaredField(filedName);
            field.setAccessible(true);
            return field.get(owner);
        } catch (NoSuchFieldException e) {
            return null;
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            return null;
        }

    }

    private Object newInstance(String className, Object[] args) throws Exception {
        Class newoneClass = Class.forName(className);

        Class[] argsClass = new Class[args.length];

        for (int i = 0, j = args.length; i < j; i++) {
            argsClass[i] = args[i].getClass();
        }

        Constructor cons = newoneClass.getConstructor(argsClass);

        return cons.newInstance(args);

    }

    private void testCipher() throws Exception {
        String input1 = "342342432424";
        String key = "e528b97251e4948d45703219eb6721e7";
        String vector = "916574485ce5983d";
        byte[] encode1 = DHCoder.encrypt(input1.getBytes(), key.getBytes(), vector.getBytes());
        System.out.println("加密:\n" + Base64.encodeToString(encode1, DEFAULT));
        System.out.println("---使用乙方本地密钥对数据库进行解密---");
        //使用乙方本地密钥对数据进行解密
        byte[] decode1 = DHCoder.decrypt(encode1, key.getBytes(), vector.getBytes());
        String output1 = new String(decode1);
        System.out.println("解密:\n" + output1);
    }

    private void rsaTest() throws Exception {
        Map<String, String> map = RSAUtil.generateKeyPair();
        String pulicKey = map.get("publicKey");
        String privateKey = map.get("privateKey");
        if (!TextUtils.isEmpty(pulicKey) && !TextUtils.isEmpty(privateKey)) {
            System.out.println("publicKey = " + pulicKey + " privateKey = " + privateKey);
        }
    }


    public class Test {
        String name;
        String age;

        public Test(String name, String age) {
            this.name = name;
            this.age = age;
        }
    }
}
